package com.example.demo.controller;

import com.example.demo.MainApp;
import com.example.demo.mapper.FileMetadataMapper;
import com.example.demo.model.dataobject.FileMetadataDO;
import com.example.demo.model.SearchOptions;
import com.example.demo.model.vo.FileModelVO;
import com.example.demo.service.FileMetadataService;
import com.example.demo.until.AutoStartUtil;
import com.example.demo.until.PortUtils;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.InputMethodEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.Window;
import org.springframework.stereotype.Controller;

import javax.annotation.Resource;
import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ResourceBundle;
import java.util.stream.Collectors;

@Controller
public class FileMetadataController implements Initializable {
    @Resource
    private FileMetadataMapper fileMetadataMapper;
    @Resource
    private FileMetadataService fileMetadataService;
    @FXML
    private MenuItem closeWindow; // 关闭菜单项
    @FXML
    private MenuItem exitButton;  // 退出菜单项
    @FXML
    private TableView<FileModelVO> fileTable;
    @FXML
    private TableColumn<FileModelVO, String> nameColumn;
    @FXML
    private TableColumn<FileModelVO, String> pathColumn;
    @FXML
    private TableColumn<FileModelVO, String> sizeColumn;
    @FXML
    private TableColumn<FileModelVO, String> modificationTimeColumn;
    @FXML
    private TextField inputField; // 绑定 FXML 中的 TextField
    @FXML
    private CheckMenuItem caseSensitiveMenuItem; // 区分大小写菜单项
    @FXML
    private CheckMenuItem fullTextMatchMenuItem; // 全文匹配菜单项
    @FXML
    private CheckMenuItem matchPathMenuItem; // 匹配路径菜单项
    @FXML
    private RadioMenuItem allMenuItem; // 所有菜单项
    @FXML
    private RadioMenuItem folderMenuItem; // 文件夹菜单项
    @FXML
    private RadioMenuItem imageMenuItem; // 图片菜单项
    @FXML
    private RadioMenuItem executableMenuItem; // 可执行文件菜单项
    @FXML
    private MenuItem openHelp; // 帮助菜单项
    @FXML
    private MenuItem openAbout; // 关于菜单项

    @FXML
    private ToggleGroup searchTypeGroup; // 单选组

    private SearchOptions searchOptionsVO = new SearchOptions(); // 搜索选项
    // 图片后缀名
    private final List<String> imageExtensions = Arrays.asList(
            "jpg", "jpeg", "png", "gif", "bmp", "tiff", "webp", "svg"
    );

    // 可执行文件后缀名
    private final List<String> executableExtensions = Arrays.asList(
            "exe", "dmg", "app", "bat", "sh", "msi", "jar", "com"
    );
    private List<Long> pids = new ArrayList<>(); // 保存所有进程的 PID
    private String processesFilePath = "D:\\JAVAaaa\\aXiangMu\\ZuJianText\\demo\\src\\main\\resources\\processesFilePath\\processes.dat";


    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // 新窗口 PID 保存
        savePidToFile();

        fileMetadataService.fileChangeSave();

        // 监听普通文本变化
        inputField.textProperty().addListener((observable, oldValue, newValue) -> {
            searchOptionsVO.setFileName(newValue);
            List<FileMetadataDO> fileMetadata = queryFileMetadata(searchOptionsVO);
            // 填充 GridPane
            populateGridPane(fileMetadata);
        });

        // 确保 ToggleGroup 已正确绑定
        if (searchTypeGroup == null) {
            System.err.println("ToggleGroup 未正确绑定！");
            return;
        }

        // 获取app名称和路径
//        String appName = MainApp.class.getSimpleName();
//        String appPath = MainApp.class.getProtectionDomain().getCodeSource().getLocation().getPath();
//        System.out.println("App Name: " + appName + ", Path: " + appPath);
//
//        try {
//            AutoStartUtil.enableAutoStart(appName,appPath);
//        } catch (IOException e) {
//            throw new RuntimeException(e);
//        }

        // 菜单栏事件监听
        handleMenuAction();

        // 查询数据库并填充数据
        List<FileMetadataDO> fileMetadataList = fileMetadataMapper.selectAll();
        // 填充 GridPane
        populateGridPane(fileMetadataList);

    }

    // 处理输入法文本变化的事件方法
    @FXML
    public void handleInputMethodTextChanged(InputMethodEvent event) {
        String committedText = event.getCommitted(); // 获取已确定的文本
        if (!committedText.isEmpty()) {
            System.out.println("中文输入已确定: " + committedText);
            // 将输入法文本追加到 TextField 中
            inputField.setText(inputField.getText() + committedText);
            // 光标后移
            inputField.positionCaret(inputField.getText().length());

            searchOptionsVO.setFileName(committedText);
            List<FileMetadataDO> fileMetadata = queryFileMetadata(searchOptionsVO);
            // 填充 GridPane
            populateGridPane(fileMetadata);
        }
    }

    @FXML
    private void openNewWindow() {
        try {
            // 获取当前 Java 命令路径
            String javaHome = System.getProperty("java.home");
            String javaBin = javaHome + "/bin/java";
            if (System.getProperty("os.name").toLowerCase().contains("win")) {
                javaBin = javaHome + "/bin/java.exe";
            }

            // 获取类路径
            String classpath = "\"" + System.getProperty("java.class.path") + "\"";

            // 获取 JavaFX 模块路径
            String javafxPath = "C:\\Program Files\\Java\\javafx-sdk-17.0.14\\lib"; // 替换为你的 JavaFX SDK 路径

            // 动态选择一个可用端口
            int availablePort = PortUtils.findAvailablePort(8080); // 默认端口为 8080

            // 构建命令
            String command = javaBin +
                    " --module-path \"" + javafxPath +
                    " --add-modules javafx.controls,javafx.fxml" +
                    " -cp " + classpath +
                    " " + MainApp.class.getName() +
                    " --server.port=" + availablePort; // 将端口作为参数传递给应用程序
            System.out.println("启动命令: " + command);

            // 启动进程
            ProcessBuilder builder = new ProcessBuilder(
                    javaBin,
                    "--module-path", javafxPath,
                    "--add-modules", "javafx.controls,javafx.fxml",
                    "-cp", classpath,
                    MainApp.class.getName(),
                    "--server.port=" + availablePort // 传递端口参数
            );
            builder.inheritIO(); // 继承输入输出
            builder.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @FXML
    public void closeWindow() {
        // 关闭当前窗口
        Stage stage = (Stage) closeWindow.getParentPopup().getOwnerWindow();
        stage.close();
    }

    @FXML
    public void closeAllWindow() {
        // 从文件中加载 PID
        pids = loadPidsFromFile();

        // 关闭当前窗口
        Stage currentStage = (Stage) exitButton.getParentPopup().getOwnerWindow();
        currentStage.close();

        // 终止所有 PID
        killProcess(8088);
        for (long pid : pids) {
            killProcess(pid);
        }

        // 清空 PID 列表
        pids.clear();

        // 清空文件内容
        clearPidFile();

        // 退出应用程序
        Platform.exit();
    }

    @FXML
    public void openHelp() {
        // 创建新窗口
        Stage modalStage = new Stage();
        modalStage.setTitle("帮助窗口");

        // 设置模态类型为 WINDOW_MODAL，阻塞主窗口
        modalStage.initModality(Modality.WINDOW_MODAL);
        Stage stage = (Stage) openHelp.getParentPopup().getOwnerWindow();
        modalStage.initOwner(stage); // 设置主窗口为所有者

        // 设置新窗口的内容
        StackPane modalRoot = new StackPane();
        Button closeButton = new Button("关闭窗口");
        closeButton.setOnAction(event -> modalStage.close()); // 点击按钮关闭窗口

        modalRoot.getChildren().add(closeButton);
        Scene modalScene = new Scene(modalRoot, 300, 400);
        modalStage.setScene(modalScene);

        // 显示模态窗口，并阻塞主窗口
        modalStage.showAndWait();
    }

    @FXML
    public void openAbout() {
        // 创建新窗口
        Stage modalStage = new Stage();
        modalStage.setTitle("帮助窗口");

        // 设置模态类型为 WINDOW_MODAL，阻塞主窗口
        modalStage.initModality(Modality.WINDOW_MODAL);
        Stage stage = (Stage) openAbout.getParentPopup().getOwnerWindow();
        modalStage.initOwner(stage); // 设置主窗口为所有者

        // 设置新窗口的内容
        StackPane modalRoot = new StackPane();
        Label label = new Label("这是一条关于信息");

        modalRoot.getChildren().add(label);
        Scene modalScene = new Scene(modalRoot, 300, 400);
        modalStage.setScene(modalScene);

        // 显示模态窗口，并阻塞主窗口
        modalStage.showAndWait();
    }

    // 填充 GridPane
    private void populateGridPane(List<FileMetadataDO> fileMetadataList) {
        // 设置列与属性的绑定
        nameColumn.setCellValueFactory(new PropertyValueFactory<>("fileName"));
        pathColumn.setCellValueFactory(new PropertyValueFactory<>("filePath"));
        sizeColumn.setCellValueFactory(new PropertyValueFactory<>("fileSize"));
        modificationTimeColumn.setCellValueFactory(new PropertyValueFactory<>("modifiedTime"));

        // 清空 fileTable
        fileTable.getItems().clear();

        List<FileModelVO> collect = fileMetadataList.stream().map((fileMetadata) -> {
            String fileSize = formatFileSize(fileMetadata.getFileSize());
            String modifiedTime = formatModifiedTime(fileMetadata.getModifiedTime());

            return FileModelVO.builder()
                    .fileName(fileMetadata.getFileName())
                    .filePath(fileMetadata.getFilePath())
                    .fileSize(fileSize)
                    .modifiedTime(modifiedTime)
                    .build();
        }).collect(Collectors.toList());

        // 填充 GridPane
        fileTable.getItems().addAll(collect);

        // 设置选中行的样式
        fileTable.setRowFactory(tv -> {
            TableRow<FileModelVO> row = new TableRow<>();
            row.setOnMouseClicked(event -> {
                if (!row.isEmpty() && event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 2) {
                    FileModelVO clickedRow = row.getItem();
                    openFileOrFolder(clickedRow.getFilePath());
                }
            });
            return row;
        });
    }


    // 打开文件或文件夹
    private void openFileOrFolder(String path) {
        try {
            String os = System.getProperty("os.name").toLowerCase();
            if (os.contains("win")) {
                // Windows
                Runtime.getRuntime().exec("cmd /c start " + path);
            } else if (os.contains("mac")) {
                // macOS
                Runtime.getRuntime().exec("open " + path);
            } else if (os.contains("nix") || os.contains("nux")) {
                // Linux
                Runtime.getRuntime().exec("xdg-open " + path);
            } else {
                System.err.println("不支持的操作系统: " + os);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 格式化文件大小
    private String formatFileSize(long fileSize) {
        if (fileSize < 1024) {
            if (fileSize == 0) {
                return " ";
            }
            return fileSize + " B";
        } else if (fileSize < 1024 * 1024) {
            return (fileSize / 1024) + " KB";
        } else {
            return (fileSize / (1024 * 1024)) + " MB";
        }
    }

    // 格式化修改时间
    private String formatModifiedTime(long modifiedTime) {
        // 将时间戳转换时间格式为yyyy/MM/dd
        java.util.Date date = new java.util.Date(modifiedTime);
        java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy/MM/dd");
        return sdf.format(date);
    }

    // 按条件查询文件
    private List<FileMetadataDO> queryFileMetadata(SearchOptions searchOptions) {

        // 根据条件查询文件元数据
        return fileMetadataMapper.selectFileMetadata(searchOptions);
    }

    // 菜单栏事件监听
    private void handleMenuAction() {
        // 监听区分大小写菜单项
        caseSensitiveMenuItem.selectedProperty().addListener((observable, oldValue, newValue) -> {
            System.out.println("区分大小写: " + newValue);
            searchOptionsVO.setCaseSensitive(newValue);
            List<FileMetadataDO> fileMetadata = queryFileMetadata(searchOptionsVO);
            // 填充 GridPane
            populateGridPane(fileMetadata);
        });

        // 监听全文匹配菜单项
        fullTextMatchMenuItem.selectedProperty().addListener((observable, oldValue, newValue) -> {
            System.out.println("全文匹配: " + newValue);
            searchOptionsVO.setFullTextMatch(newValue);
            List<FileMetadataDO> fileMetadata = queryFileMetadata(searchOptionsVO);
            // 填充 GridPane
            populateGridPane(fileMetadata);
        });

        // 监听匹配路径菜单项
        matchPathMenuItem.selectedProperty().addListener((observable, oldValue, newValue) -> {
            System.out.println("匹配路径: " + newValue);
            searchOptionsVO.setMatchPath(newValue);
            List<FileMetadataDO> fileMetadata = queryFileMetadata(searchOptionsVO);
            // 填充 GridPane
            populateGridPane(fileMetadata);
        });
        // 监听 ToggleGroup 的选择变化
        searchTypeGroup.selectedToggleProperty().addListener((observable, oldValue, newValue) -> {
            if (newValue == null) {
                System.out.println("未选中任何选项");
                return;
            }

            if (newValue == allMenuItem) {
                System.out.println("选中: 所有");
                searchOptionsVO.setFolder(false);
                searchOptionsVO.setFileType(null);
                List<FileMetadataDO> fileMetadata = queryFileMetadata(searchOptionsVO);
                // 填充 GridPane
                populateGridPane(fileMetadata);
            } else if (newValue == folderMenuItem) {
                System.out.println("选中: 文件夹");
                searchOptionsVO.setFolder(true);
                searchOptionsVO.setFileType(null);
                List<FileMetadataDO> fileMetadata = queryFileMetadata(searchOptionsVO);
                // 填充 GridPane
                populateGridPane(fileMetadata);
            } else if (newValue == imageMenuItem) {
                System.out.println("选中: 图片");
                searchOptionsVO.setFolder(false);
                searchOptionsVO.setFileType(imageExtensions);
                List<FileMetadataDO> fileMetadata = queryFileMetadata(searchOptionsVO);
                // 填充 GridPane
                populateGridPane(fileMetadata);
            } else if (newValue == executableMenuItem) {
                System.out.println("选中: 可执行文件");
                searchOptionsVO.setFolder(false);
                searchOptionsVO.setFileType(executableExtensions);
                List<FileMetadataDO> fileMetadata = queryFileMetadata(searchOptionsVO);
                // 填充 GridPane
                populateGridPane(fileMetadata);
            }
        });

    }

    // 保存 PID 到文件
    private void savePidToFile() {
        // 获取当前程序的PID
        long currentPid = ProcessHandle.current().pid();
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(processesFilePath, true))) {
            writer.write(String.valueOf(currentPid)); // 写入 PID
            writer.newLine(); // 换行
            System.out.println("保存PID: " + currentPid);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 从文件中加载 PID
    private List<Long> loadPidsFromFile() {
        List<Long> pids = new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(new FileReader(processesFilePath))) {
            String line;
            while ((line = reader.readLine()) != null) {
                pids.add(Long.parseLong(line.trim())); // 读取每行 PID
            }
            System.out.println("读出PID: " + pids);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return pids;
    }

    // 终止进程
    private void killProcess(long pid) {
        try {
            String os = System.getProperty("os.name").toLowerCase();
            ProcessBuilder processBuilder;
            if (os.contains("win")) {
                // Windows 系统
                processBuilder = new ProcessBuilder("taskkill", "/F", "/PID", String.valueOf(pid));
            } else {
                // Linux/Mac 系统
                processBuilder = new ProcessBuilder("kill", "-9", String.valueOf(pid));
            }
            processBuilder.start().waitFor();
            System.out.println("结束进程: " + pid);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 清空文件内容
    private void clearPidFile() {
        try (FileWriter writer = new FileWriter(processesFilePath, false)) {
            writer.write(""); // 清空文件内容
            System.out.println("清楚文件中的PID");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}